/*
 * Copyright 2008 Nathan C Jones
 * 
 * This file is part of Fivehundred.
 * 
 * Fivehundred is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * Fivehundred is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * Fivehundred. If not, see <http://www.gnu.org/licenses/>. 
 */

package com.googlecode.fivehundred.ui.simple;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;

import com.googlecode.fivehundred.model.Card;
import com.googlecode.fivehundred.model.CardRenderer;
import com.googlecode.fivehundred.svg.DefaultCardBackRenderer;

public class JCard extends JComponent {

	/** Serial Version UID generated 2007-10-16T23:08. */
	private static final long serialVersionUID = 1987152678352965228L;

	private Card card;

	/**
	 * The card face is visible.
	 */
	private boolean faceUp = false;

	private Image cardImage;

	private Image cardBackImage;

	public JCard(Card card) {
		this(card, CardRenderer.DEFAULT_WIDTH);
	}

	@Override
	public Rectangle getBounds(Rectangle rv) {
		// TODO Auto-generated method stub
		Rectangle r = super.getBounds(rv);
		r.setSize(getPreferredSize());
		return r;
	}

	public JCard(Card card, final int width, final boolean faceUp) {
		this.faceUp = faceUp;
		this.card = card;
		final int height = calculateHeight(width);
		setPreferredSize(new Dimension(width, height));
		cardImage = card.getCardRenderer().getImage(width, height);

		cardBackImage = new DefaultCardBackRenderer().getImage(width, height);

	}

	public JCard(final Card card, final int width) {
		this(card, width, true);
	}

	public static int calculateHeight(final int width) {
		return (int) (width * Math.sqrt(2));
	}

	public Card getCard() {
		return card;
	}

	public boolean isFaceUp() {
		return faceUp;
	}

	public void setFaceUp(boolean faceUp) {
		if (faceUp != this.faceUp) {
			this.faceUp = faceUp;
			this.repaint();
		}
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		Graphics2D g2 = (Graphics2D) g;
		int cornerSize = this.cardImage.getWidth(null) / 7;

		if (faceUp) {
			g2.setColor(Color.white);
			g2.fillRoundRect(0, 0, this.cardImage.getWidth(null) - 1, cardImage.getHeight(null) - 1, cornerSize, cornerSize);
			g2.drawImage(isFaceUp() ? cardImage : cardBackImage, 0, 0, null);
		} else {
			Dimension d = getPreferredSize();
			//TODO cache texture image
			BufferedImage textureImage = new BufferedImage(d.width,d.height, BufferedImage.TYPE_INT_ARGB);
			textureImage.createGraphics().drawImage(cardBackImage, 0, 0, null);
			g2.setPaint(new TexturePaint(textureImage, new Rectangle2D.Double(0d, 0d, (double)d.width, (double)d.height)));
			g2.fillRoundRect(0, 0, this.cardImage.getWidth(null) - 1, cardImage.getHeight(null) - 1, cornerSize, cornerSize);
		}
		g2.setColor(Color.gray);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		g2.drawRoundRect(0, 0, this.cardImage.getWidth(null) - 1, cardImage.getHeight(null) - 1, cornerSize, cornerSize);
	}

	@Override
	public boolean contains(int x, int y) {
		// TODO extract the rectangle so both the paint and contains methods can use it 
		Dimension d = getPreferredSize();
		float arc = (float)d.width/7;
		Shape rectangle = new RoundRectangle2D.Float(0f,0f,(float)d.width,(float)d.height,arc, arc);
		return rectangle.contains(new Point(x,y));
	}

	@Override
	public void update(Graphics g) {
		paint(g);
	}

	public void flip() {
		setFaceUp(!faceUp);
	}

	@Override
	public String toString() {
		return "JCard[" + this.card.toString() + "]";
	}
}
